import random
from django import forms
from django.conf import settings
from django.core.validators import RegexValidator ## 正则表达式使用的模块
from django.core.exceptions import ValidationError ## 正则表达式校验错误的模块
from utils.tencent import sms
from web import models
from django_redis import get_redis_connection # 导入模块django_redis
# 创建注册的modelform
class RegisterModelForm(forms.ModelForm):
    mobile_phone = forms.CharField(
        label='手机号码',
        validators=[RegexValidator(r'^(1[3|4|5|6|7|8|9])\d{9}$','手机号格式错误')]
        ) ## 重写手机号码字段，在它生成的输入框中输入数据时会进行validators=[]正则表达式的校验
    password = forms.CharField(label='密码',widget=forms.PasswordInput()) ## 利用插件将密码框改成密码类型的输入框，输入数据时将显示...或者***
    # 利用参数attrs重写样式。当用下面的__init__方法重写样式时，就不需要在这里添加了
    confirm_password = forms.CharField(
        label='确认密码',
        widget=forms.PasswordInput(attrs={'class':'form-control','placeholder':'确认密码'})
        )## 数据表中有这个字段将重写，没有这个字段将新增这个字段。
    code = forms.CharField(
        label='验证码',
        widget=forms.PasswordInput(attrs={'class': 'form-control', 'placeholder': '确认密码'})
        )

    class Meta:
        model = models.UserInfo
        fields = '__all__'
    ## 判断是否有样式，有的话就重写class和placeholder，没有的话就直接覆盖添加
    def __init__(self,*args,**kwargs):
        super().__init__(*args,**kwargs)
        for name,field in self.fields.items():
            if field.widget:
                field.widget.attrs['class'] = 'form-control'
                field.widget.attrs['placeholder'] = field.label
            else:
                field.widget.attrs={'class': 'form-control', 'placeholder': field.label}


# 对通过后端推送过来的数据进行校验
class SendSmsForm(forms.Form):
    mobile_phone = forms.CharField(label='手机号',validators=[RegexValidator(r'^(1[3|4|5|6|7|8|9])\d{9}$','手机号格式错误')])
    ## 通过重写__init__()方法，让类SendSmsForm能多携带一个参数request过来，request就可以把tpl的数据携带过来，从而进行校验
    def __init__(self,request,*args,**kwargs):
        super().__init__(*args,**kwargs)
        self.request = request

    # 要想校验手机号码是否已经注册过，需要用到mobile_phone的钩子方法。钩子方法的cleaned_data中包含通过校验的所有的数据
    def clean_mobile_phone(self):
        mobile_phone = self.cleaned_data['mobile_phone']  ## 验证通过的(上面的验证即手机号码错误的验证)才能让钩子函数获取到，否则获取的是null

        # 获取前端推送过来的tpl,和settings.py中保存的tpl进行比较，用来判断tpl的数据是否有误
        tpl = self.request.GET.get('tpl')  ## 获取前端推送过来的tpl
        template_id = settings.TENCENT_SMS_TEMPLATE.get(tpl) ## 获取settings.py中保存的tpl
        if not template_id:
            raise ValidationError('模版错误')

        exists = models.UserInfo.objects.filter(mobile_phone=mobile_phone).exists() ## 在数据库中查询获取的手机号是否存在记录，返回的结果为bool值
        if exists:
            raise ValidationError('手机号码已被注册')
        # 发短信，并且写redis
        code = random.randrange(1000,9999)
        result = sms.send_sms_single(mobile_phone,template_id,[code,])
        if result['result'] != 0:
            raise ValidationError('短信发送失败，{}'.format(result['errmsg']))
        conn = get_redis_connection()  ## 利用django自带的模块，建立redis连接池，并设置连接池中的数据和超时的时间
        conn.set(mobile_phone,code,ex=60)
        return code   ## 返回的是什么数据，在用form.save()保存的时候数据库里将会保存什么数据。即这个返回的数据决定了字段mobile_phone的数值




